/*
 * Copyright 2010 Alexey Romensky
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

/*
 * User: Alexey Romensky
 * Date: 20.02.2010
 * Time: 6:36:36
 */
package com.googlecode.gwt.logging.window.client;

import com.extjs.gxt.ui.client.core.El;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.widget.Html;
import com.extjs.gxt.ui.client.widget.Window;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.layout.TableData;
import com.extjs.gxt.ui.client.widget.layout.TableLayout;
import com.googlecode.gwt.logging.base.client.Appender;
import com.googlecode.gwt.logging.base.client.util.Level;

import java.util.ArrayList;
import java.util.List;

import static com.extjs.gxt.ui.client.Style.Scroll.AUTO;
import static java.util.Arrays.asList;

public class WindowAppender implements Appender {

    private Window window;

    private String buffer = "";

    private final String name;

    public WindowAppender(String name) {
        this.name = name;
    }

    @Override
    public void append(Level level, String message) {

        if (window == null) {

            window = new Window();
            final TableLayout layout = new TableLayout();
            window.setLayout(layout);
            window.setHeading(this.name);
            window.setWidth(800);
            window.setHeight(600);
            window.setScrollMode(AUTO);
            window.setMaximizable(true);
            window.setCollapsible(true);

            window.addButton(new Button("Clear", new SelectionListener<ButtonEvent>() {

                @Override
                public void componentSelected(ButtonEvent ce) {
                    window.removeAll();
                }
            }));

            window.addButton(new Button("Close", new SelectionListener<ButtonEvent>() {

                @Override
                public void componentSelected(ButtonEvent ce) {
                    window.hide();
                }
            }));


            window.show();
        }

        final List<String> lines = new ArrayList<String>();

        final String[] strings = message.split("\\n", -1);
        if (strings.length > 1) {
            lines.add(buffer + strings[0]);
            lines.addAll(asList(strings).subList(1, strings.length - 1));
        }
        buffer = strings[strings.length - 1];

        if (lines.size() > 0) {

            final boolean scrollNeeded = isScrollNeeded();

            for (String line : lines) {

                final Html widget =
                        new Html(line.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;"));
                widget.addStyleName("log-row");
                window.add(widget, new TableData());

                while (window.getItemCount() > 1000) {
                    window.remove(window.getItem(0));
                }
            }

            window.layout();

            if (scrollNeeded) {
                scrollDown();
            }
        }
    }

    private void scrollDown() {

        final El target = window.getLayoutTarget();
        final El table = target.getChild(0);
        final int height = table.getHeight();
        target.setScrollTop(height);
    }

    private boolean isScrollNeeded() {

        final El target = window.getLayoutTarget();
        final El table = target.getChild(0);

        final int scrollTop = target.getScrollTop();
        final int viewportHeight = target.getClientHeight();
        final int contentHeight = table.getHeight();

        return scrollTop + viewportHeight >= contentHeight;
    }
}
